package com.trade.okxserver.api;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.util.concurrent.RateLimiter;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.trade.okxserver.constants.UrlConstants;
import com.trade.okxserver.req.KLineReq;
import com.trade.okxserver.res.PublicDataRes;
import com.trade.okxserver.res.Result;
import com.trade.okxserver.res.Trades;
import com.trade.okxserver.util.HttpUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class PublicData {

    Cache<String, List<PublicDataRes>> cache = Caffeine.newBuilder()
            .maximumSize(500)
            .build();

    @Resource
    private HttpUtils httpUtils;

    private RateLimiter rateLimiter = RateLimiter.create(6);
    private RateLimiter tradesRateLimiter = RateLimiter.create(8);

    public List<PublicDataRes> instruments(String instId) {
//        List<PublicDataRes> instruments = cache.getIfPresent("instruments");
//        if (CollectionUtils.isEmpty(instruments)) {
            Map<String, Object> params = new HashMap<>();
            params.put("instType", "SWAP");
            if(StringUtils.isNotBlank(instId)){
                params.put("instId", instId);
            }
            String res = httpUtils.get(UrlConstants.INSTRUMENTS, params);
            Result<List<PublicDataRes>> result = new Gson().fromJson(res, new TypeToken<Result<List<PublicDataRes>>>() {
            }.getType());
            if (result.getCode().equals("0")) {
                cache.put("instruments", result.getData());
            }
            return result.getData();
//        }
//        return instruments;
    }

    public List<List<Double>> kLine(KLineReq req) {
        Map<String, Object> params = new HashMap<>();
        params.put("instId", req.instId());
        if (StringUtils.isNotBlank(req.bar())) {
            params.put("bar", req.bar());
        }
        if (StringUtils.isNotBlank(req.after())) {
            params.put("after", req.after());
        }
        if (StringUtils.isNotBlank(req.before())) {
            params.put("before", req.before());
        }
        if (StringUtils.isNotBlank(req.limit())) {
            params.put("limit", req.limit());
        }
        String res = httpUtils.get(UrlConstants.CANDLES, params);
        Result<List<List<Double>>> result = new Gson().fromJson(res, new TypeToken<Result<List<List<Double>>>>() {
        }.getType());

        if (result.getCode().equals("0")) {
            return result.getData();
        } else {
            log.warn("获取数据异常 {}", res);
        }
        return Collections.EMPTY_LIST;
    }

    public List<List<String>> kLineHistory(KLineReq req) {
        rateLimiter.acquire();
        Map<String, Object> params = new HashMap<>();
        params.put("instId", req.instId());
        if (StringUtils.isNotBlank(req.bar())) {
            params.put("bar", req.bar());
        }
        if (StringUtils.isNotBlank(req.after())) {
            params.put("after", req.after());
        }
        if (StringUtils.isNotBlank(req.before())) {
            params.put("before", req.before());
        }
        if (StringUtils.isNotBlank(req.limit())) {
            params.put("limit", req.limit());
        }
        String res = httpUtils.get(UrlConstants.HISTORY_CANDLES, params);
        Result<List<List<String>>> result = new Gson().fromJson(res, new TypeToken<Result<List<List<String>>>>() {
        }.getType());

        if (result.getCode().equals("0")) {
            return result.getData();
        } else {
            log.warn("获取数据异常 {}", res);
        }
        return Collections.EMPTY_LIST;
    }

    public List<Trades> trades(KLineReq req) {
        tradesRateLimiter.acquire();
        Map<String, Object> params = new HashMap<>();
        params.put("instId", req.instId());
        params.put("limit", 500);
        String res = httpUtils.get(UrlConstants.TRADES, params);
        Result<List<Trades>> result = new Gson().fromJson(res, new TypeToken<Result<List<Trades>>>() {
        }.getType());

        if (result.getCode().equals("0")) {
            return result.getData();
        } else {
            log.warn("获取数据异常 {}", res);
        }
        return Collections.EMPTY_LIST;
    }

}
